﻿namespace JoinBox.WPF.LabelBarStandard.View;
using Application = System.Windows.Forms.Application;

public static class AnchorHelper
{
    /// <summary>
    /// 拖放操作
    /// </summary>
    /// <param name="control"></param>
    public static ControlDragDrop DragDrop(System.Windows.Controls.Control control)
    {
        return new ControlDragDrop(control, (cddSender, cddEventArgs) => {
            try
            {
                var path = ((Array)cddEventArgs.Data.GetData(System.Windows.DataFormats.FileDrop))?
                           .GetValue(0)?
                           .ToString();
                if (path == null)
                {
                    AutoGo.Printl("**** 拖拉的路径失败");
                    return;
                }

                string extension = Path.GetExtension(path).ToLower();// 扩展名
                if (extension == ".dll")
                {
                    AutoGo.Printl("**** 执行加载dll操作");

                    AssemblyDependent ad = new();
                    List<LoadState> loadStates = new();
                    ad.Load(path, loadStates);
                    var msg = AssemblyDependent.PrintMessage(loadStates);
                    if (msg != null)
                        AutoGo.Printl(msg);
                }
                else if (extension == ".dwg")
                {
                    // 前台打开图纸
                    AutoGo.Post(() => {
                        Opendwg(path);
                    });
                }
                else
                {
                    AutoGo.Printl("**** 你拖拉的是什么玩意,不支持加载");
                }
            }
            catch (Exception ee)
            {
                AutoGo.Printl("**** 加载出现错误::" + Environment.NewLine + ee.Message);
            }
        });
    }

    /// <summary>
    /// 在cad的前台打开dwg
    /// </summary>
    /// <param name="strFileName"></param>
    public static bool Opendwg(string strFileName)
    {
        if (!File.Exists(strFileName))
        {
            AutoGo.Printl("此文件不存在: " + strFileName);
            return false;
        }

        try
        {
            var dm = Acap.DocumentManager;
#if NET35
            dm.Open(strFileName, false);
#elif NET40
            Autodesk.AutoCAD.ApplicationServices
            .DocumentCollectionExtension
            .Open(dm, strFileName, false);
#else
            dm.AppContextOpenDocument(strFileName);
#endif
        }
        catch (System.Exception e)
        {
            AutoGo.Printl("\n此文件打开错误: " + strFileName + "\n错误信息:" + e.Message);
            return false;
        }
        return true;
    }

    /// <summary>
    /// 预留客户区空间嵌入
    /// </summary>
    /// <param name="lParam">窗口Rect信息用于修改</param>
    public static void SqueezeSize(IntPtr lParam)
    {
        // nc消息要算窗口大小,预留一个空间出来放窗口,它可以缩小其他窗口的空间,而不是把WPF遮蔽到上面去
        // 非托管内存块->托管对象
        var str = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(lParam, typeof(NCCALCSIZE_PARAMS));
        // 预留高度,如果不-2会超出来一点点
        str.rgrc[0].Top = str.rgrc[0].Top + Convert.ToInt32(DocumentTab.HeightDPI - 2);
        // 托管对象->非托管内存块
        Marshal.StructureToPtr(str, lParam, true);
        AutoGo.Printl("**** 预留客户区空间成功!");
    }

    /// <summary>
    /// 获取要设置的尺寸信息
    /// </summary>
    /// <param name="handle"></param>
    public static (int x, int y, int w, int h) GetSizeInfo(IntPtr handle)
    {
        // 返回客户区大小
        GetClientRect(AutoGo.AcapMainSyncEx.Handle, out RECT lpRect);

        // 客户区左上角转为屏幕坐标
        var lpPoint = new Point(lpRect.Left, lpRect.Top);
        ClientToScreen(AutoGo.AcapMainSyncEx.Handle, ref lpPoint);

        // 返回cad文档管理器窗口边框尺寸
        _ = GetWindowRect(AutoGo.AcapMidSyncEx.Handle, out RECT midRect);

        var x = midRect.Left - lpPoint.X;
        var y = midRect.Top - lpPoint.Y;

        // 获得当前屏幕的大小
        var sr = Screen.AllScreens[0].WorkingArea;

        // 用win32的方法实现移动,
        // 这里高度增加,会令整体高度拉高,而控件在中间
        if (handle != IntPtr.Zero)
        {
            int midWidth = midRect.Right - midRect.Left;
            var rect = new RECT(x, y, x + midWidth, y + DocumentTab.HeightDPI);
            MoveWindow(handle, rect);
        }
        return (x, y, sr.Width, DocumentTab.HeightDPI);
    }

    // 鼠标按着文档窗口移动时候触发 WM.WM_MOUSEACTIVATE
    // https://social.msdn.microsoft.com/Forums/en-US/572cf1ac-c55f-47cb-b41c-bbc0d7fd23b8/wndproc-detect-title-bar-clicked

    // 这里是可用的,但是拖动文档窗口会频繁发生,
    // 拦截每个文档栏的拖动又会产生消息通知滞后,所以不想做了
    // 拖动窗口/最大化/还原等尺寸改变时候触发,触发比WM_SIZE多
    // 调整cad文档尺寸
    // 这里只是拦截cad主窗口改变大小

    /// <summary>
    /// 调整文档正常态时候的大小
    /// </summary>
    /// <param name="isMax">最大化时候计算贴边</param>
    public static void ReWindowSize(bool isMax = false)
    {
        var doca = Acap.DocumentManager.MdiActiveDocument;
        if (doca == null)
            return;

        // 有一个文档是正常态,其他都会是
        var ws = GetWindowPlacement(doca.Window.Handle);
        if (ws.showCmd != NCmdShow.SW_SHOWNORMAL)// 处于窗口正常态
            return;

        // cad窗口大小
        _ = GetWindowRect(Acap.MainWindow.Handle, out RECT rect_acad);
        // cad文档管理器窗口大小
        var handle_Mdi = GetParent(doca.Window.Handle);
        _ = GetWindowRect(handle_Mdi, out RECT rect_Mdi);

        // 获取桌面大小 https://www.cnblogs.com/chlyzone/archive/2012/11/05/2754601.html
        // 桌面高度(无任务栏) -  cad高 - cad到桌面顶
        int ab = 0;
        if (isMax)// 最大化的时候加
            ab = SystemInformation.WorkingArea.Height - rect_acad.Height;
        var H = rect_Mdi.Height - DocumentTab.HeightDPI + ab;

        // 最大化时候文档底边贴边,做不到!Mdi大小的控制很奇怪
        // 文档高不变
        // H = rect_doc.Bottom - rect_doc.Top;

        // 会令刷新有奇怪的效果
        // WinApi.MoveWindow(handle_Mdi, rect_Mdi, true);

        // winform界面处理消息队列,否则会令界面卡黑色边
        Application.DoEvents();

        foreach (Document doc in Acap.DocumentManager)
        {
            var handle_doc = doc.Window.Handle;

            // 如果被文档栏遮盖,就挤小这个文档,并平移它到下面去,相当于挤开它
            // 获取文档窗口位置信息
            _ = GetWindowRect(handle_doc, out RECT rect_doc);

            // 文档-管理器,cad每条边都预留了2,所以改成0,窗口就会一直溜走
            var X = rect_doc.Left - rect_Mdi.Left;
            if (X < 0)
                X = 2;

            // 文档超过右边就贴边
            var W = rect_doc.Right - rect_Mdi.Right;
            if (W > 0)
                W = rect_doc.Width - W;
            else
                W = rect_doc.Width;

            // Y=0,文档永远贴上沿
            _ = MoveWindow(handle_doc, X - 2, 0, W, H, true);
        }
    }
}